#include "clib_backtrace.h"
#include <cxxabi.h>
#ifndef __USE_GNU
#define __USE_GNU
#endif
#include <dlfcn.h>
#undef __USE_GNU

#include <stdio.h>
#include <stdlib.h>
#include <execinfo.h>

static const i32_t clib_trace_max = 256;

i32_t
clib_backtrace(i32_t skip)
{
    i08_t buf[4096];
    void *callstack[clib_trace_max];
    int frames = backtrace(callstack, clib_trace_max);
    char **symbols = backtrace_symbols(callstack, frames);
    for (int i = skip; i < frames; i++) {
        Dl_info info;
        if (dladdr(callstack[i], &info) && info.dli_sname) {
            char *demangled = NULL;
            int status = -1;
            snprintf(buf, sizeof(buf), "%-3d %*p %s + %zd\n",
                     i, (int)(2 + sizeof(void*) * 2), callstack[i],
                     status == 0 ? demangled :
                     info.dli_sname == 0 ? symbols[i] : info.dli_sname,
                     (char *)callstack[i] - (char *)info.dli_saddr);
  
        } else {
            snprintf(buf, sizeof(buf), "%-3d %*p %s\n",
                     i, (int)(2 + sizeof(void*) * 2), callstack[i], symbols[i]);
        }
    }
    return 0;
}